package com.zero2oneit.mall.search.service.impl;


import com.zero2oneit.mall.common.utils.EsIndexConstant;
import com.zero2oneit.mall.common.utils.R;
import com.zero2oneit.mall.common.utils.StringUtils;
import com.zero2oneit.mall.common.utils.bootstrap.BoostrapDataGrid;
import com.zero2oneit.mall.search.config.ESConfig;
import com.zero2oneit.mall.search.service.TcBusinessEsService;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;

/**
 * Description:
 *
 * @author yjj
 * @date 2020/12/15 10:05
 */
@Service
public class TcBusinessEsServiceImpl implements TcBusinessEsService {

    @Autowired
    private RestHighLevelClient esClient;

    @Override
    public R tcBusinDistance(Map<String,String> map) {
        SearchRequest searchRequest = new SearchRequest();
        //指定索引
        searchRequest.indices(EsIndexConstant.TCBUSIN_INFO);
        Double latitude = Double.valueOf(map.get("lat"));
        Double longitude = Double.valueOf(map.get("log"));
        String distance = map.get("distance");
        Integer from = Integer.valueOf(map.get("from"));
        //设置搜索半径
        GeoDistanceQueryBuilder queryBuilder = geoDistanceQuery("localhost")
                .point(latitude,longitude)
                .distance(distance, DistanceUnit.KILOMETERS)
                .geoDistance(GeoDistance.PLANE);
        //按距离排序
        GeoDistanceSortBuilder sort = SortBuilders.geoDistanceSort("localhost",latitude,longitude);
        sort.order(SortOrder.ASC);
        sort.point(latitude,longitude);
        BoolQueryBuilder boolQueryBuilder = boolQuery().must(termQuery("useStatus",1));;
        //构建检索
        SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.searchSource();
        if(!StringUtils.isEmpty(map.get("categoryIds"))){
            boolQueryBuilder.must(boolQuery().should(termsQuery("categoryIds",map.get("categoryIds")))
                    .should(wildcardQuery("categoryIds", "*," + map.get("categoryIds") + ",*"))
                    .should(wildcardQuery("categoryIds", "*," + map.get("categoryIds")))
                    .should(wildcardQuery("categoryIds",map.get("categoryIds")+",*")));
        }
        if (StringUtils.isEmpty(map.get("keyword"))){
            boolQueryBuilder.must(queryBuilder);
            searchSourceBuilder.from(from)
                    .size(10)
                    .query(boolQueryBuilder)
                    .sort(sort);
        }else {
            boolQueryBuilder.must(matchPhraseQuery("storeName",map.get("keyword"))).must(queryBuilder);
            searchSourceBuilder.from(0)
                    .size(10)
                    .query(boolQueryBuilder)
                    .sort(sort);
        }
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = null;
        try {
            searchResponse = esClient.search(searchRequest, ESConfig.COMMON_OPTIONS);
        } catch (IOException e) {
            e.printStackTrace();
        }
        SearchHits searchHits = searchResponse .getHits();
        long value = searchResponse.getHits().getTotalHits().value;
        int total= (int) value;
        ArrayList<Map> arrayList = new ArrayList<>();
        searchHits.forEach(hit->{
            Map map2 = new HashMap();
            map2.put("storeName", hit.getSourceAsMap().get("storeName"));
            map2.put("businessId", hit.getSourceAsMap().get("businessId"));
            map2.put("sale", hit.getSourceAsMap().get("sale"));
            map2.put("fromDel", hit.getSourceAsMap().get("fromDel"));
            map2.put("peopleConsume", hit.getSourceAsMap().get("peopleConsume"));
            map2.put("storePicture", hit.getSourceAsMap().get("storePicture"));
            map2.put("storeImage", hit.getSourceAsMap().get("storeImage"));
            map2.put("delivery", hit.getSourceAsMap().get("delivery"));
            //获取距离值，并保留两位小数点
            BigDecimal geoDis = new BigDecimal((Double) hit.getSortValues()[0]);
            //坐标
            Map<String, Object> hitMap = hit.getSourceAsMap();
            //计算距离
            hitMap.put("geoDistance", geoDis.setScale(0, BigDecimal.ROUND_HALF_DOWN));
            map2.put("range", hit.getSourceAsMap().get("geoDistance"));
            arrayList.add(map2);
        });
        BoostrapDataGrid boostrapDataGrid =new BoostrapDataGrid(total,total==0? Collections.EMPTY_LIST : arrayList);
        return R.ok(boostrapDataGrid);
    }

    @Override
    public R tcBusinSales(Map<String, String> map) {
        SearchRequest searchRequest = new SearchRequest();
        //指定索引
        searchRequest.indices(EsIndexConstant.TCBUSIN_INFO);
        SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.searchSource();
        Double latitude = Double.valueOf(map.get("lat"));
        Double longitude = Double.valueOf(map.get("log"));
        Integer from = Integer.valueOf(map.get("from"));
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //设置搜索半径
        GeoDistanceQueryBuilder queryBuilder = QueryBuilders.geoDistanceQuery("localhost")
                .point(latitude,longitude)
                .distance("1200",DistanceUnit.KILOMETERS)
                .geoDistance(GeoDistance.PLANE);
        boolQueryBuilder.must(queryBuilder);
        boolQueryBuilder.must(termQuery("useStatus",1));
        GeoDistanceSortBuilder geoSort = SortBuilders.geoDistanceSort("localhost",latitude,longitude);
        geoSort.order(SortOrder.ASC);
        geoSort.point(latitude,longitude);
        if(!StringUtils.isEmpty(map.get("sort"))){
            String sort = map.get("sort");
            if (sort.equals("sale")){
                FieldSortBuilder sale = new FieldSortBuilder("sale").order(SortOrder.DESC);
                searchSourceBuilder.sort(sale);
            } else if (sort.equals("DESC")){
                FieldSortBuilder sale = new FieldSortBuilder("peopleConsume").order(SortOrder.DESC);
                searchSourceBuilder.sort(sale);
            }else if (sort.equals("ASC")){
                FieldSortBuilder sale = new FieldSortBuilder("peopleConsume").order(SortOrder.ASC);
                searchSourceBuilder.sort(sale);
            }
        }
        if (!StringUtils.isEmpty(map.get("keyword"))){
            boolQueryBuilder.must(QueryBuilders.matchQuery("storeName",map.get("keyword")));
        }
        if(!StringUtils.isEmpty(map.get("categoryIds"))){
            boolQueryBuilder.must(boolQuery().should(termsQuery("categoryIds",map.get("categoryIds")))
                    .should(wildcardQuery("categoryIds", "*," + map.get("categoryIds") + ",*"))
                    .should(wildcardQuery("categoryIds", "*," + map.get("categoryIds")))
                    .should(wildcardQuery("categoryIds",map.get("categoryIds")+",*")));
        }
        searchSourceBuilder.query(boolQueryBuilder);
        searchSourceBuilder.sort(geoSort);
        searchSourceBuilder.from(from*10);
        searchSourceBuilder.size(10);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = null;
        try {
            searchResponse = esClient.search(searchRequest, ESConfig.COMMON_OPTIONS);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取内容
        SearchHits searchHits = searchResponse .getHits();
        long value = searchResponse.getHits().getTotalHits().value;
        int total= (int) value;
        List<Map> list =new ArrayList<>();
        searchHits.forEach(hit->{
            Map map2 = new HashMap();
            map2.put("storeName", hit.getSourceAsMap().get("storeName"));
            map2.put("businessId", hit.getSourceAsMap().get("businessId"));
            map2.put("sale", hit.getSourceAsMap().get("sale"));
            map2.put("fromDel", hit.getSourceAsMap().get("fromDel"));
            map2.put("peopleConsume", hit.getSourceAsMap().get("peopleConsume"));
            map2.put("storeImage", hit.getSourceAsMap().get("storeImage"));
            map2.put("storePicture", hit.getSourceAsMap().get("storePicture"));
            map2.put("delivery", hit.getSourceAsMap().get("delivery"));
            //获取距离值，并保留两位小数点
            BigDecimal geoDis=null;
            if(!StringUtils.isEmpty(map.get("sort"))){
                 geoDis = new BigDecimal((Double) hit.getSortValues()[1]);
            }else {
                 geoDis = new BigDecimal((Double) hit.getSortValues()[0]);
            }
            //坐标
            Map<String, Object> hitMap = hit.getSourceAsMap();
            //计算距离
            hitMap.put("geoDistance", geoDis.setScale(0, BigDecimal.ROUND_HALF_DOWN));
            map2.put("range", hit.getSourceAsMap().get("geoDistance"));
            list.add(map2);
        });
        BoostrapDataGrid boostrapDataGrid =new BoostrapDataGrid(total,total==0? Collections.EMPTY_LIST : list);
        return R.ok(boostrapDataGrid);
    }

    @Override
    public R tcBusinById(Map<String, String> map) {
//        String id= "1334057516165431297";
        if (!StringUtils.isEmpty(map.get("id"))){
            String id=map.get("id");
            SearchRequest searchRequest = new SearchRequest();
            //指定索引
            searchRequest.indices(EsIndexConstant.TCBUSIN_INFO);
            SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.searchSource();
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
                    .must(termQuery("_id",id))
                    .must(termQuery("useStatus",1));
            searchSourceBuilder.query(boolQueryBuilder);
            searchRequest.source(searchSourceBuilder);
            SearchResponse searchResponse = null;
            try {
                searchResponse = esClient.search(searchRequest, ESConfig.COMMON_OPTIONS);
            } catch (IOException e) {
                e.printStackTrace();
            }
            //获取内容
            SearchHit[] searchHits = searchResponse .getHits().getHits();
            List<Map> list =new ArrayList<>();
            List<SearchHit> searchHitList=Arrays.asList(searchHits);
            searchHitList.forEach(hit->{
                Map map2 = new HashMap();
                map2.put("storeName", hit.getSourceAsMap().get("storeName"));
                map2.put("businessId", hit.getSourceAsMap().get("businessId"));
                map2.put("sale", hit.getSourceAsMap().get("sale"));
                map2.put("fromDel", hit.getSourceAsMap().get("fromDel"));
                map2.put("peopleConsume", hit.getSourceAsMap().get("peopleConsume"));
                map2.put("storeImage", hit.getSourceAsMap().get("storeImage"));
                map2.put("storePicture", hit.getSourceAsMap().get("storePicture"));
                map2.put("delivery", hit.getSourceAsMap().get("delivery"));
                list.add(map2);
            });
            return R.ok(list);
        }
        return R.fail();
    }
}
